#ifdef _ARRAY_H_

using namespace std;

template <class T> const int Array<T>::ITEM_NOT_FOUND = -1;

template <class T> 
Array<T>::Array(  int size, int step )
{
	m_dataSize = 0;
	m_initSize = size;
	m_arraySize = m_initSize;
	m_increaseStep = step;
	m_data = NULL;	
	m_data = new T[ m_initSize ];
}

template <class T>
Array<T>::~Array( void )
{
	//destroy();
}

template <class T>
Array<T>::Array( const Array<T>& copy )
{
	m_initSize = copy.m_initSize;
	m_increaseStep = copy.m_increaseStep;
	m_dataSize = copy.m_dataSize;
	m_arraySize = copy.m_arraySize;
	m_data = new T [ m_arraySize ];
	memcpy( (void * ) m_data, ( void * ) copy.m_data, m_arraySize * sizeof( T ) );
}

template <class T>
T& Array<T>::operator[]( int ind )
{
	return m_data[ ind ];
}

template <class T>
void Array<T>::operator<<( T item )
{
	
	if( m_dataSize == m_arraySize )
	{
		increaseArraySize();
	}
	m_data[ m_dataSize ] = item;
	m_dataSize++;
}

template <class T>
T& Array<T>::get( int indice )
{
	return m_data[ indice ];
}

template <class T>
void Array<T>::push( T item )
{
	if( m_dataSize == m_arraySize )
	{
		increaseArraySize();
	}
	m_data[ m_dataSize ] = item;
	m_dataSize++;	
}

template <class T>
void Array<T>::push( T * items, int itemsSize )
{ 
	
	if( m_dataSize + itemsSize >= m_arraySize )
	{
		increaseArraySize( itemsSize );
	}
	memcpy( (void *) &m_data[ m_dataSize ], (void *) items, itemsSize * sizeof( T ) );
	m_dataSize = m_dataSize + itemsSize;
}

template <class T>
int Array<T>::getSize( void )
{
	return m_dataSize;
}

template <class T>
int Array<T>::getArraySize( void )
{
	return m_arraySize;
}

template <class T>
T * Array<T>::getArrayPointer( void )
{
	return m_data;
}

template <class T>
void Array<T>::clear( void )
{
	if( m_data != NULL )
	{
		delete [] m_data;
		m_data = new T[ m_initSize ];
	}
	else
	{
		m_data = new T[ m_initSize ];
	}
	m_dataSize = 0;
}

template <class T>
void Array<T>::destroy( void )
{
	if( m_data != NULL )
	{
		delete [] m_data;
	}
}

template <class T>
int Array<T>::findItem( T item, int begin )
{
	if( begin < m_dataSize )
	{
		for( int i = begin; i < m_dataSize; i++ )
		{
			if( item == m_data[i] )
			{
				return i;
			}
		}			
	}	
	return -1;
}

template <class T>
void  Array<T>::remove( int indice )
{
	for( int i = indice + 1; i < m_dataSize; i++ )
	{
		m_data[ i - 1 ] = m_data[ i ];
	}
	
	m_dataSize--;
}

template <class T>
void  Array<T>::removeFirst( T item )
{
	for( int i = 0; i < m_dataSize; i++ )
	{
		if( item == m_data[ i ] )
		{
			remove( i );
			return;
		}
	}
}

template <class T>
void  Array<T>::removeAll( T item )
{
	for( int i = 0; i < m_dataSize; i++ )
	{
		if( item == m_data[ i ] )
		{
			remove( i );
			i--;
		}
	}
}

template <class T>
void Array<T>::increaseArraySize( int step )
{
	if( step == -1 )
	{
		step = m_increaseStep;
	}
	
	T * newData;
	newData = new T[ m_dataSize + step ];
	memcpy ( newData, m_data, m_dataSize * sizeof( T ) ); 
	delete [] m_data;
	
	m_data = newData;
	m_arraySize = m_arraySize + step;
}

template <class T>
void Array<T>::insertAt( T item, int indice )
{
	if( m_dataSize == m_arraySize )
	{
		increaseArraySize();
	}
	
	// Move all the data table 1 position right
	for( int i = m_dataSize; i > indice; --i ) {
		m_data[ i ] = m_data[ i - 1 ];
	}
	m_dataSize++;
	m_data[ indice ] = item;	
}
#endif
